Skip to content

Transfer authorization to manager signature authentication, reducing the possibility of key authentication leakage#259

Open
Admirepowered wants to merge 11 commits intobmax121:mainfrom
Admirepowered:main
Open

Transfer authorization to manager signature authentication, reducing the possibility of key authentication leakage#259
Admirepowered wants to merge 11 commits intobmax121:mainfrom
Admirepowered:main

Conversation

@Admirepowered
Copy link
Copy Markdown
Collaborator

No description provided.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR shifts privileged command authorization from a “superkey” model toward an Android “trusted manager” model, where a manager app is identified via APK signature digest + package UID, and then used to gate su/supercmd/supercall behaviors.

Changes:

  • Add trusted-manager discovery/refresh logic (APK path discovery + signature/cert digest check + packages.list UID lookup) and use it to authorize privileged flows on Android.
  • Update supercmd/supercall authorization to allow trusted-manager UID in addition to existing allowlists, plus add boot-event refresh hooks.
  • Add iterate_dir ksym plumbing and a PI_MAP patch condition fix.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tools/patch.c Fixes PI_MAP patch condition handling for newer kernel versions.
kernel/patch/ksyms/misc.c Adds/matches iterate_dir and enables matching call_usermodehelper.
kernel/patch/include/userd.h Adds Android trusted-manager API declarations and includes ktypes.h.
kernel/patch/common/user_event.c Refreshes trusted-manager state on boot events and logs results.
kernel/patch/common/supercmd.c Extends authorization to trusted-manager UID; adds reload-cfg logging.
kernel/patch/common/supercall.c Extends authorization to trusted-manager UID; adds trusted-manager wrapper.
kernel/patch/android/userd.c Implements trusted-manager identification (APK scan + signature digest) and auto-su on exec for trusted-manager.
kernel/linux/include/linux/fs.h Introduces dir_context + iterate_dir() wrapper for ksym-based directory scanning.
kernel/.gitignore Expands ignored build/artifact patterns.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread kernel/patch/android/userd.c Outdated
Comment on lines +217 to +218
uint8_t cert_buf[APK_CERT_MAX_LENGTH];

Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apk_sig_block_matches_trusted_digest() allocates a 4096-byte cert_buf on the stack. Kernel stack space is tight, and this function is called from deeper call chains during boot/event handling; this size risks stack overflow on some configs. Prefer allocating the certificate buffer dynamically (e.g., kmalloc/kvzalloc) or reusing a shared buffer, and ensure it’s freed on all paths.

Copilot uses AI. Check for mistakes.
Comment on lines +154 to +168
static int path_has_suffix(const char *path, const char *suffix)
{
loff_t off = 0;
set_priv_sel_allow(current, true);
size_t path_len;
size_t suffix_len;
if (!path || !suffix) return 0;
path_len = strlen(path);
suffix_len = strlen(suffix);
if (path_len < suffix_len) return 0;
return strcmp(path + path_len - suffix_len, suffix) == 0;
}

static int path_is_exact(const char *path, const char *target)
{
return path && target && strcmp(path, target) == 0;
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

path_has_suffix() and path_is_exact() are newly added but currently unused in this file, which will trigger -Wunused-function warnings under -Wall and adds dead code to maintain. Either remove them or use them where appropriate.

Copilot uses AI. Check for mistakes.
int refresh_trusted_manager_state(void);
int is_trusted_manager_uid(uid_t uid);
uid_t get_trusted_manager_uid(void);

Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

userd.h declares is_trusted_manager_uid() only under #ifdef ANDROID, but common code paths (e.g., patch/common/supercmd.c) now call it outside #ifdef ANDROID. To avoid non-Android build breakage and keep the API consistent, consider declaring is_trusted_manager_uid() unconditionally in the header (with a safe non-Android stub/implementation that denies by default).

Suggested change
#else
static inline int is_trusted_manager_uid(uid_t uid)
{
(void)uid;
return 0;
}

Copilot uses AI. Check for mistakes.
Comment on lines 344 to 351
is_key_auth = 1;
} else if (!strcmp("su", arg1)) {
uid_t uid = current_uid();
if (!is_su_allow_uid(uid)) return;
if (!is_su_allow_uid(uid) && !is_trusted_manager_uid(uid)) return;
su_allow_uid_profile(0, uid, &profile);
} else {
return;
if (!is_trusted_manager_uid(current_uid())) return;
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handle_supercmd() now calls is_trusted_manager_uid() in the non-#ifdef ANDROID control flow, but this file only includes <userd.h> when ANDROID is defined. In non-Android builds (supported by the Makefile), this will be a hard compile error (no prototype) and also changes authorization behavior unexpectedly. Consider either (a) wrapping the trusted-manager checks in #ifdef ANDROID and preserving the previous non-Android behavior, or (b) including <userd.h> unconditionally and providing a safe non-Android implementation of is_trusted_manager_uid() that denies by default.

Copilot uses AI. Check for mistakes.
#ifdef ANDROID
return is_trusted_manager_uid_android(uid);
#endif
return 1;
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In non-Android builds, is_trusted_manager_uid() currently returns 1, which effectively treats every UID as a trusted manager. That makes the new authorization checks no-ops and can unintentionally widen access (e.g., allowing su for any UID). Returning 0 (deny) when ANDROID is not defined would preserve the pre-existing non-Android security posture.

Suggested change
return 1;
return 0;

Copilot uses AI. Check for mistakes.
Comment on lines +461 to 464
int trust_rc = refresh_trusted_manager_state();
int config_rc = load_ap_package_config();
log_boot("reload-cfg: refresh rc=%d package_config rc=%d\n", trust_rc, config_rc);
cmd_res.msg = "reload package config success";
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reload-cfg command logs refresh_trusted_manager_state() / load_ap_package_config() return codes but always reports success to the caller. If either call fails, the command output should reflect that (e.g., set cmd_res.rc / cmd_res.err_msg or choose a failure message) so users don’t get a false positive.

Suggested change
int trust_rc = refresh_trusted_manager_state();
int config_rc = load_ap_package_config();
log_boot("reload-cfg: refresh rc=%d package_config rc=%d\n", trust_rc, config_rc);
cmd_res.msg = "reload package config success";
static char reload_cfg_err[128];
int trust_rc = refresh_trusted_manager_state();
int config_rc = load_ap_package_config();
log_boot("reload-cfg: refresh rc=%d package_config rc=%d\n", trust_rc, config_rc);
if (trust_rc || config_rc) {
cmd_res.rc = trust_rc ? trust_rc : config_rc;
snprintf(reload_cfg_err, sizeof(reload_cfg_err),
"reload package config failed: refresh rc=%d package_config rc=%d",
trust_rc, config_rc);
cmd_res.err_msg = reload_cfg_err;
} else {
cmd_res.msg = "reload package config success";
}

Copilot uses AI. Check for mistakes.
Comment on lines 137 to +146
*len = vfs_llseek(filp, 0, SEEK_END);
vfs_llseek(filp, 0, SEEK_SET);
data = vmalloc(*len);
data = vmalloc(*len + 1);
if (!data) {
filp_close(filp, 0);
goto out;
}
loff_t pos = 0;
kernel_read(filp, data, *len, &pos);
((char *)data)[*len] = '\0';
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kernel_read_file() uses vfs_llseek() to populate *len and then immediately does vmalloc(*len + 1) and reads *len bytes. If vfs_llseek() fails and returns a negative value, this will turn into a huge allocation attempt (and *len + 1 can also overflow). Add validation that *len is >= 0 and within a reasonable upper bound before allocating/reading.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants